/*
 * Copyright 2002-2006 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.tigris.springframework.utils;

import java.util.*;
import java.util.concurrent.*;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * @author Sam Huang
 * 
 */
public class ConfigurationHandler extends DefaultHandler {

	protected Bean bean;

	protected String buffer;

	protected String propertyName;

	protected String propertyValue;

	protected List<Bean> beans;

	protected Queue<String> importedFiles = null;

	public ConfigurationHandler(String fileName) throws Exception {

		beans = new ArrayList<Bean>();

		importedFiles = new ConcurrentLinkedQueue<String>();

		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser sp = spf.newSAXParser();

		importedFiles.add(fileName);

		// parse the file and also register this class for call backs
		while (!importedFiles.isEmpty()) {
			sp.parse(importedFiles.poll(), this);
		}

		consolidate();
	}

	public List<Bean> getBeans() {
		return beans;
	}

	@Override
	public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
		// TODO Auto-generated method stub
		super.characters(arg0, arg1, arg2);
		buffer = new String(arg0, arg1, arg2);
	}

	@Override
	public void endElement(String arg0, String arg1, String arg2)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(arg0, arg1, arg2);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
	 *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
	 */
	@Override
	public void startElement(String arg0, String arg1, String arg2,
			Attributes arg3) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(arg0, arg1, arg2, arg3);
		if (arg2.equals("bean")) {
			bean = new Bean();
			bean.setId(arg3.getValue("id"));
			bean.setClassName(arg3.getValue("class"));
			beans.add(bean);
		} else if (arg2.equals("property")) {
			propertyName = arg3.getValue("name");
		} else if (arg2.equals("ref")) {
			propertyValue = arg3.getValue("bean");
			bean.addProperty(propertyName, propertyValue);
		} else if (arg2.equals("import")) {
			importedFiles.add(arg3.getValue("resource"));
		}
	}

	protected static Bean getBean(String id, List<Bean> beans) {
		for (Bean bean : beans) {
			if (bean.getId().equals(id)) {
				return bean;
			}
		}
		return null;
	}

	protected void consolidate() {
		for (Bean bean : beans) {
			for (Iterator<Object> propertyName = bean.getProperties().keySet()
					.iterator(); propertyName.hasNext();) {
				String name = (String) propertyName.next();
				String value = (String) bean.getProperties().get(name);
				Bean property = getBean(value, beans);
				bean.addProperty(name, property);
			}
		}
	}
}
